#! /usr/bin/env/python3
# _*_ coding:utf-8 _*_
'''
    名称：求素数
    作者：王楠
    版本：1.0
    日期：2020/03/05
    练习：filter() 筛选函数的使用
         迭代器的使用 以及yield  和迭代器调用next()
    算法：   计算素数的一个方法是埃氏筛法，它的算法理解起来非常简单：
            首先，列出从2开始的所有自然数，构造一个序列：
            2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...
            取序列的第一个数2，它一定是素数，然后用2把序列的2的倍数筛掉：
            3,  5, 7,  9,11, 13, 15, 17, 19, ...
            取新序列的第一个数3，它一定是素数，然后用3把序列的3的倍数筛掉：
            5, 7, 11, 13, 17, 19, ...
            取新序列的第一个数5，然后用5把序列的5的倍数筛掉：
            7, 11, 13, 17, 19, ...
            不断筛下去，就可以得到所有的素数。
'''


def num():
    '''
    生成器函数：生成所有的从3开始的奇数
    '''
    n = 1
    while True:
        n += 2
        yield n


def _not_divisible(n):
    """
    筛选函数
    """
    return lambda x: x % n != 0


def primes():
    """
    生成器函数，不断生成下一个素数
    """
    yield 2  # 第一次生成第一个素数2
    it = num()  # it是 生成器对象 初始为 num（）这个生成器，后续根据规则筛选
    while True:
        n = next(it)  # next 下一个 的 第一个值
        # print(n)
        yield n
        it = filter(_not_divisible(n), it)  # 构造新生成序列 赋值于it，即用规则更新后续序列
        # for i in it:
        #     print(i)


def main():
    '''
    主函数
    '''
    max_num = input('求素数工具，退出请输入:q。请输入最大值：')
    while True:
        if max_num != 'q':
            max_num = int(max_num)
            print('小于{}的素数如下:'.format(max_num))
            for n in primes():
                if n < max_num:
                    print(n, end='  ')
                else:
                    break
            print()
            print('××××××××××××××××××××××××××××××××××××××××××')
            max_num = input('求素数工具，退出请输入:q。请输入最大值：')
        else:
            print('程序退出')
            break


if __name__ == '__main__':
    main()
